﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.ComponentModel;
using System.Reflection;
using System.Web;
using System.Web.Compilation;
using System.IO;
using System.Collections.Specialized;
using System.Linq.Expressions;
using System.Data;

namespace System.Web.Mvc {
    public static class CheckBoxExtension {
        #region CheckBox List

        /// <summary>
        /// Creates an HTML Checkbox list based on the passed-in datasource.
        /// </summary>
        /// <param name="dataSource">IEnumerable, IQueryable, DataSet, DataTable, or IDataReader</param>
        /// <param name="htmlName">The name of the control for the page</param>
        public static string[] CheckBoxList(this HtmlHelper helper, string htmlName, object dataSource) {
            return CheckBoxList(helper, htmlName, dataSource, "", "", new string[0], null);
        }
        /// <summary>
        /// Creates an HTML Checkbox list based on the passed-in datasource.
        /// </summary>
        /// <param name="dataSource">IEnumerable, IQueryable, DataSet, DataTable, or IDataReader</param>
        /// <param name="htmlName">The name of the control for the page</param>
        /// <param name="selectedValues">An IEnumerable list of values to be selected in the list</param>
        public static string[] CheckBoxList(this HtmlHelper helper, string htmlName, object dataSource, IEnumerable selectedValues) {

            return CheckBoxList(helper, htmlName, dataSource, "", "", selectedValues, null);
        }

        /// <summary>
        /// Creates an HTML Checkbox list based on the passed-in datasource.
        /// </summary>
        /// <param name="dataSource">IEnumerable, IQueryable, DataSet, DataTable, or IDataReader</param>
        /// <param name="htmlName">The name of the control for the page</param>
        /// <param name="textField">The datasource field to use for the the display text & value</param>
        public static string[] CheckBoxList(this HtmlHelper helper, string htmlName, object dataSource, string textField) {
            return CheckBoxList(helper, htmlName, dataSource, textField, textField, new string[0], null);
        }

        /// <summary>
        /// Creates an HTML Checkbox list based on the passed-in datasource.
        /// </summary>
        /// <param name="dataSource">IEnumerable, IQueryable, DataSet, DataTable, or IDataReader</param>
        /// <param name="htmlName">The name of the control for the page</param>
        /// <param name="textField">The datasource field to use for the the display text</param>
        /// <param name="valueField">The datasource field to use for the the control value</param>
        public static string[] CheckBoxList(this HtmlHelper helper, string htmlName, object dataSource, string textField, string valueField) {
            return CheckBoxList(helper, htmlName, dataSource, textField, valueField, new string[0], null);
        }
        /// <summary>
        /// Creates an HTML Checkbox list based on the passed-in datasource.
        /// </summary>
        /// <param name="dataSource">IEnumerable, IQueryable, DataSet, DataTable, or IDataReader</param>
        /// <param name="htmlName">The name of the control for the page</param>
        /// <param name="textField">The datasource field to use for the the display text</param>
        /// <param name="valueField">The datasource field to use for the the control value</param>
        /// <param name="htmlAttributes">Any attributes you want set on the tag. Use anonymous-type declaration for this: new{class=cssclass}</param>
        public static string[] CheckBoxList(this HtmlHelper helper, string htmlName, object dataSource, string textField, string valueField, object htmlAttributes) {
            return CheckBoxList(helper, htmlName, dataSource, textField, valueField, new string[0], htmlAttributes);
        }
        /// <summary>
        /// Creates an HTML Checkbox list based on the passed-in datasource.
        /// </summary>
        /// <param name="dataSource">IEnumerable, IQueryable, DataSet, DataTable, or IDataReader</param>
        /// <param name="htmlName">The name of the control for the page</param>
        /// <param name="textField">The datasource field to use for the the display text</param>
        /// <param name="valueField">The datasource field to use for the the control value</param>
        /// <param name="selectedValues">An IEnumerable list of values to be selected in the list</param>
        public static string[] CheckBoxList(this HtmlHelper helper, string htmlName, object dataSource, string textField, string valueField, IEnumerable selectedValues) {
            return CheckBoxList(helper, htmlName, dataSource, textField, valueField, selectedValues, null);
        }

        /// <summary>
        /// Creates an HTML Checkbox list based on the passed-in datasource.
        /// </summary>
        /// <param name="dataSource">IEnumerable, IQueryable, DataSet, DataTable, or IDataReader</param>
        /// <param name="htmlName">The name of the control for the page</param>
        /// <param name="textField">The datasource field to use for the the display text</param>
        /// <param name="valueField">The datasource field to use for the the control value</param>
        /// <param name="selectedValues">An IEnumerable list of values to be selected in the list</param>
        /// <param name="htmlAttributes">Any attributes you want set on the tag. Use anonymous-type declaration for this: new{class=cssclass}</param>
        public static string[] CheckBoxList(this HtmlHelper helper, string htmlName, object dataSource, string textField, string valueField, IEnumerable selectedValues, object htmlAttributes) {
            Hashtable setHash = HtmlExtensionUtility.GetPropertyHash(htmlAttributes);

            //output
            StringBuilder sb = new StringBuilder();
            DataTable tbl = MvcControlDataBinder.EvalDataSource(dataSource, textField, valueField);

            string attributeList = string.Empty;
            if (setHash != null)
                attributeList = setHash.ToAttributeList();

            //loop the source
            foreach (DataRow dr in tbl.Rows) {
                string selectedFlag = string.Empty;
                string thisValue = dr[0].ToString();
                string thisText = dr[1].ToString();
                bool isChecked = false;
                //enumerate the selections
                IEnumerator en = selectedValues.GetEnumerator();
                while (en.MoveNext()) {
                    isChecked = HtmlExtensionUtility.AreEqual(en.Current, thisValue);
                    if (isChecked)
                        break;
                }
                string checkbox = CheckBox(helper, htmlName, thisText, thisValue, isChecked, htmlAttributes) + "|";
                sb.Append(checkbox);
            }

            string result = sb.ToString();
            string[] resultList = result.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            return resultList;
        }

        #endregion
        
        #region CheckBox
        /// <summary>
        /// Creates a checkbox input for your form
        /// </summary>
        /// <param name="htmlName">The name and ID of the control</param>
        /// <param name="value">The text for the control</param>
        /// <param name="isChecked">Whether the checkbox is selected</param>
        public static string CheckBox(this HtmlHelper helper, string htmlName, string text, string value, bool isChecked) {
            return CheckBox(helper, htmlName, text, value, isChecked, null);

        }
        /// <summary>
        /// Creates a checkbox input for your form
        /// </summary>
        /// <param name="htmlName">The name and ID of the control</param>
        /// <param name="text">The text & value for the control</param>
        public static string CheckBox(this HtmlHelper helper, string htmlName, string text) {
            return CheckBox(helper, htmlName, text, text, false, null);
        }

        /// <summary>
        /// Creates a checkbox input for your form
        /// </summary>
        /// <param name="htmlName">The name and ID of the control</param>
        /// <param name="text">The text & value for the control</param>
        /// <param name="value">The text for the control</param>
        public static string CheckBox(this HtmlHelper helper, string htmlName, string text, string value) {
            return CheckBox(helper, htmlName, text, value, false, null);
        }

        /// <summary>
        /// Creates a checkbox input for your form
        /// </summary>
        /// <param name="htmlName">The name and ID of the control</param>
        /// <param name="text">The text & value for the control</param>
        /// <param name="isChecked">Whether the checkbox is selected</param>
        public static string CheckBox(this HtmlHelper helper, string htmlName, string text, bool isChecked) {
            return CheckBox(helper, htmlName, text, text, isChecked, null);
        }
        /// <summary>
        /// Creates a checkbox input for your form
        /// </summary>
        /// <param name="htmlName">The name and ID of the control</param>
        /// <param name="text">The text for the control</param>
        /// <param name="value">The value for the control</param>
        /// <param name="isChecked">Whether the checkbox is selected</param>
        /// <param name="htmlAttributes">Any attributes you want set on the tag. Use anonymous-type declaration for this: new{class=cssclass}</param>
        public static string CheckBox(this HtmlHelper helper, string htmlName, string text, string value, bool isChecked, object htmlAttributes) {
            string cbFormat = "<input type=\"checkbox\" id=\"{0}\" name=\"{0}\" value=\"{1}\" {2} {3}/>{4}";

            string atts = string.Empty;
            if (htmlAttributes != null)
                atts = htmlAttributes.ToAttributeList();

            string checkedFlag = isChecked ? "checked=checked" : "";

            return string.Format(cbFormat, htmlName, helper.Encode(value.ToString()), checkedFlag, atts, helper.Encode(text));

        }
        #endregion

    }
}
